package com.onec.service.customer.service.online;

import com.onec.service.api.dto.request.channel.ChannelMerchantReq;
import com.onec.service.api.dto.request.gateway.BizContent;
import com.onec.service.api.dto.request.route.RouteReq;
import com.onec.service.api.dto.response.customer.MerchantResp;
import com.onec.service.api.dto.response.route.RouteResp;
import com.onec.service.api.enums.ProductEnum;
import com.onec.service.api.enums.ResultCodeEnum;
import com.onec.service.api.enums.ServiceTradeEnum;
import com.onec.service.api.enums.error.MerchantErrorEnum;
import com.onec.service.api.exception.CustomerException;
import com.onec.service.api.exception.RouteException;
import com.onec.service.api.service.channel.ChannelMerchantApiService;
import com.onec.service.api.service.route.RouteRiskApiService;
import com.onec.service.customer.entity.agent.AgentFee;
import com.onec.service.customer.entity.merchant.MerchantBusiness;
import com.onec.service.customer.entity.merchant.MerchantInfo;
import com.onec.service.customer.service.AgentFeeService;
import com.onec.service.customer.service.MerchantAccountService;
import com.onec.service.customer.service.MerchantBusinessService;
import com.onec.service.customer.service.MerchantInfoService;
import com.onec.service.service.AgentInfoService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;

import java.math.BigDecimal;

/**
 * @author ONEC
 */
public abstract class BaseOnlineDefaultService implements OnlineBaseService {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaseOnlineDefaultService.class);

    @Autowired
    protected ApplicationContext applicationContext;
    @Autowired
    protected RabbitTemplate rabbitTemplate;

    @Autowired
    protected AgentFeeService agentFeeService;
    @Autowired
    protected AgentInfoService agentInfoService;
    @Autowired
    protected MerchantInfoService merchantInfoService;
    @Autowired
    protected MerchantAccountService merchantAccountService;
    @Autowired
    protected MerchantBusinessService merchantBusinessService;

    @DubboReference(version = "1.0.1", timeout = 6000)
    protected RouteRiskApiService routeRiskApiService;

    @DubboReference(version = "1.0.1", timeout = 6000)
    protected ChannelMerchantApiService channelMerchantApiService;

    /**
     * 交易请求类型商户类：
     *
     * @param bizContent
     * @return
     */
    @Override
    public MerchantResp execute(BizContent bizContent) {
        return setStatus(ResultCodeEnum.SERVER_ERROR);
    }

    /**
     * 到changl 通道注册商户！
     *
     * @return
     */
    @Async
    protected void registerChannel(BizContent bizContent, MerchantInfo merchantInfo) {
        ChannelMerchantReq channelMerchantReq = new ChannelMerchantReq(bizContent);
        channelMerchantReq.setMerchantNo(merchantInfo.getCode());
        channelMerchantApiService.register(channelMerchantReq);
    }

    /**
     * 商户信息提交到风控系统：
     *
     * @param bizContent
     * @return
     */
    public RouteResp checkRouteCustomer(BizContent bizContent) {
        RouteReq routeReq = new RouteReq(bizContent);
        RouteResp routeResp = routeRiskApiService.getRouteByCustomerRisk(routeReq);
        if (!routeResp.isSuccess()) {
            throw new RouteException(routeResp.getCode(), routeResp.getMessage());
        }
        return routeResp;
    }

    /**
     * 自动加入到风控数据：
     *
     * @param bizContent
     * @return
     */
    @Async(value = "addRouteCustomer")
    public boolean addRouteCustomer(BizContent bizContent, ServiceTradeEnum serviceTradeEnum) {
        RouteReq routeReq = new RouteReq(bizContent);
        return routeRiskApiService.addRiskRouteInfo(routeReq, serviceTradeEnum);
    }

    /**
     * 产品开通/产品费率变更，验证请求参数：
     *
     * @param bizContent bizContent 产品信息：
     * @param agentId    机构id
     */
    protected void validateProductFee(BizContent bizContent, Long agentId) {

        AgentFee agentFee = agentFeeService.getAvailableAgentFee(agentId, bizContent.getBusinessNo());

        BigDecimal merchantRate = new BigDecimal(bizContent.getRate());
        // 验证是否超过机构费率：
        this.checkRateFeeValue(agentFee.getRate(), merchantRate);
        // 验证是否超过最大费率：
        this.checkMaxFeeValue(agentFee.getMaxRate(), merchantRate);
        // 验证提现手续
        BigDecimal _merchantFee = new BigDecimal(bizContent.getFee());
        this.checkRateFeeValue(agentFee.getFee(), _merchantFee);
        this.checkMaxFeeValue(agentFee.getMaxFee(), _merchantFee);
    }

    /**
     * 验证交易手续费，机构和商户费率的问题：高于机构费率：
     *
     * @param agentRate    机构费率
     * @param merchantRate 商户费率
     */
    protected boolean checkRateFeeValue(BigDecimal agentRate, BigDecimal merchantRate) {
        if (agentRate.compareTo(new BigDecimal("0")) <= 0) {
            throw new CustomerException(MerchantErrorEnum.AGENT_FEE_INFO_ERROR, String.valueOf(agentRate));
        }
        if (merchantRate.compareTo(new BigDecimal("0")) <= 0) {
            throw new CustomerException(MerchantErrorEnum.MERCHANT_FEE_INFO_ERROR, String.valueOf(merchantRate));
        }
        if (merchantRate.compareTo(agentRate) < 0) {
            throw new CustomerException(MerchantErrorEnum.MERCHANT_FEE_AGENT_ERROR, String.valueOf(agentRate));
        }
        return false;
    }

    /**
     * 手续费：，
     * 低于，机构的最大费率；
     */
    protected boolean checkMaxFeeValue(BigDecimal agentFee, BigDecimal merchantFee) {
        if (merchantFee.compareTo(agentFee) >= 0) {
            throw new CustomerException(MerchantErrorEnum.AGENT_FEE_MAX_FEE_ERROR, String.valueOf(agentFee));
        }
        return false;
    }

    /**
     * 机构商户编号和商户机构编号：
     */
    protected void checkAgentNo(String merchantAgentNo, String agentNo) {
        if (!merchantAgentNo.equals(agentNo)) {
            throw new CustomerException(MerchantErrorEnum.MERCHANT_AGENT_INFO_ERROR, merchantAgentNo);
        }
    }

    /**
     * 验证产品 是否可用
     */
    protected void checkProduct(String product) {
        if (!ProductEnum.isInclude(product)) {
            throw new CustomerException(MerchantErrorEnum.PRODUCT_ERROR, product);
        }
    }


    /**
     * 下游：商户注册成功返回参数：
     *
     * @param
     * @param merchantInfo
     */
    public MerchantResp respRegisterOk(MerchantInfo merchantInfo) {
        MerchantResp merchantResp = setStatus(ResultCodeEnum.SUCCESS);
        merchantResp.setStatus(merchantInfo.getStatus().name());
        merchantResp.setMerchantNo(merchantInfo.getCode());
        return merchantResp;
    }

    /**
     * 商户业务开通成功返回参数：
     *
     * @param
     * @param
     */
    public MerchantResp respOpenProduct(MerchantBusiness merchantBusiness, BizContent bizContent) {
        MerchantResp merchantResp = setStatus(ResultCodeEnum.SUCCESS);
        merchantResp.setStatus(merchantBusiness.getStatus().name());
        merchantResp.setRate(merchantBusiness.getMerchantRate());
        merchantResp.setFee(merchantBusiness.getMerchantFee());
        merchantResp.setMerchantNo(bizContent.getMerchantNo());
        merchantResp.setBusinessNo(bizContent.getBusinessNo());
        return merchantResp;
    }


    /**
     * @param resultCodeEnum
     * @return
     */
    private MerchantResp setStatus(ResultCodeEnum resultCodeEnum) {
        return new MerchantResp(resultCodeEnum);
    }
}
